<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>音频流</title>
    <style>
        .button {
            background-color: #4CAF50;
            /* 绿色背景 */
            color: white;
            /* 白色文字 */
            padding: 15px 32px;
            /* 内边距 */
            text-align: center;
            /* 文字居中 */
            text-decoration: none;
            /* 去掉下划线 */
            display: inline-block;
            /* 行内块元素 */
            font-size: 16px;
            /* 字体大小 */
            margin: 4px 2px;
            /* 外边距 */
            cursor: pointer;
            /* 鼠标悬停时显示为手型 */
            border-radius: 4px;
            /* 圆角边框 */
            border: none;
            /* 去掉边框 */
        }

        /* 定义鼠标悬停时按钮的样式 */
        .button:hover {
            background-color: #45a049;
            /* 更深的绿色背景 */
        }
    </style>
</head>

<body>
    <h1>音频流测试</h1>
    <button class="button" id="playBtn">开始播放(移动设备若没有声音，请尝试点击)</button>
    <button class="button" id="listenBtn">开始监听</button>
    <button class="button" id="stop_listen_Button">停止录音</button>
    <script>

        const CHANNELS = 1;
        const RATE = 16000;
        const SAMPLESIZE = 16;
        const CHUNK = 512;
        const ws = new WebSocket('wss://' + window.location.hostname + ':' + window.location.port + '/ws');

        let audioContext_play;
        let audioSource_play;
        let audioContext_listen;
        let audioSource_listen;
        let stream_listen;
        let processorNode;
        let Send_falg = false;

        // if (!("AudioContext" in window) || !("webkitAudioContext" in window)||!("audioWorklet" in AudioContext.prototype)) {
        //     alert("您的浏览器不支持AudioContext录音功能，请升级到支持该功能的浏览器！");
        // }

        let index_now = 0;
        let audio_listen_buffer
        switch (SAMPLESIZE) {
            case 8:
                audio_listen_buffer = new Int8Array(CHUNK);
                break;
            case 16:
                audio_listen_buffer = new Int16Array(CHUNK);
                break;
            case 24:
                audio_listen_buffer = new Int32Array(CHUNK);
                break;
            case 32:
                audio_listen_buffer = new Int32Array(CHUNK);
                break;
        }



        function playAudio(data) {
            if (!audioContext_play) {
                audioContext_play = new (window.AudioContext || window.webkitAudioContext)();
            }

            if (audioSource_play) {
                audioSource_play.disconnect();
            }

            const audioBuffer = audioContext_play.createBuffer(CHANNELS, CHUNK, RATE);
            const channelData = audioBuffer.getChannelData(0);
            for (let i = 0; i < CHUNK; i++) {
                // 将 int16 转换为 float32，范围 [-1.0, 1.0]
                channelData[i] = data[i] / 32767.0;
            }

            audioSource_play = audioContext_play.createBufferSource();
            audioSource_play.buffer = audioBuffer;
            audioSource_play.connect(audioContext_play.destination);
            audioSource_play.start(0);
        }

        ws.binaryType = 'arraybuffer'; // 确保接收二进制数据

        ws.onmessage = function (event) {
            let audioData
            switch (SAMPLESIZE) {
                case 8:
                    audioData = new Int8Array(event.data);
                    break;
                case 16:
                    audioData = new Int16Array(event.data);
                    break;
                case 24:
                    audioData = new Int32Array();
                    for (let i = 0; i < event.data.byteLength; i += 3) {
                        audioData[i / 3] = (event.data[i] << 16) + (event.data[i + 1] << 8) + event.data[i + 2];
                    }
                    break;
                case 32:
                    audioData = new Int32Array(event.data);
                    break;
            }
            playAudio(audioData);
            console.log(audioData);
        };

        ws.onerror = function (error) {
            console.error('WebSocket 错误:', error);
        };

        ws.onclose = function () {
            console.log('WebSocket 连接已关闭');
        };
        document.getElementById('playBtn').addEventListener('click', function () {
            audioSource_play.start(0);
        });


        // 监听
        // 获取麦克风权限并录音

        async function startRecording() {
            index_now = 0;
            switch (SAMPLESIZE) {
                case 8:
                    audio_listen_buffer = new Int8Array(CHUNK);
                    break;
                case 16:
                    audio_listen_buffer = new Int16Array(CHUNK);
                    break;
                case 24:
                    audio_listen_buffer = new Int32Array(CHUNK);
                    break;
                case 32:
                    audio_listen_buffer = new Int32Array(CHUNK);
                    break;
            }
            send_flag = true;
            stream_listen = await navigator.mediaDevices.getUserMedia({
                audio: {
                    sampleRate: RATE,
                    channelCount: CHANNELS,
                    sampleSize: SAMPLESIZE
                }
            });
            audioContext_listen = new AudioContext();
            audioSource_listen = audioContext_listen.createMediaStreamSource(stream_listen);
            await audioContext_listen.audioWorklet.addModule('recorder-worklet.js');
            processorNode = new AudioWorkletNode(audioContext_listen, 'recorder-worklet');
            audioSource_listen.connect(processorNode);
            // audioSource_listen.connect(processorNode).connect(audioContext_listen.destination);
            audioSource_listen.connect(processorNode);
            processorNode.port.onmessage = function (event) {
                if (send_flag) {
                    n=event.data.length;
                    for (let i = 0; i < n; i++) {
                        audio_listen_buffer[index_now] = event.data[i];
                        index_now++;
                    }
                    if (index_now >= CHUNK) {
                        index_now = 0;
                        ws.send(audio_listen_buffer.buffer);
                        // console.log(audio_listen_buffer.buffer);
                        console.log(audio_listen_buffer);
                    }
                }
            }
        }

        document.getElementById('listenBtn').addEventListener('click', startRecording);
        function stopRecording() {
            send_flag = false;
            stream_listen.getTracks().forEach(track => track.stop());
            // 3. 断开节点连接
            if (processorNode) {
                processorNode.disconnect();
                processorNode = null;
            }
            // 2. 关闭音频上下文
            if (audioContext_listen) {
                audioContext_listen.close();
                audioContext_listen = null;
            }


            // 4. 释放资源引用
            audioSource_listen = null;
        }
        document.getElementById('stop_listen_Button').addEventListener('click', function () {
            stopRecording();
        });


    </script>
</body>

</html>